/*
 * Copyright (c) 2007 The University of Reading
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University of Reading, nor the names of the
 *    authors or contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package uk.ac.rdg.resc.wms2kml;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.simpleframework.xml.load.Commit;
import ucar.nc2.units.DateFormatter;

/**
 * Interface describing WMS layer types.
 *
 * @author Jon Blower
 * $Revision$
 * $Date$
 * $Log$
 */
public abstract class Layer
{
    private int numOverlays = 1;
    protected List<String> supportedProjections = new ArrayList<String>();
    private boolean includeInKml = false;
    private Layer parent = null;
    
    public abstract String getName();

    public abstract String getTitle();

    public abstract String getDescription();

    /**
     * @return the children Layers, or an empty List if this Layer has no children
     */
    public abstract List<? extends Layer> getChildren();
    
    public abstract BoundingBox getBbox();
    
    /**
     * @return a list of possible values of elevation that this Layer can
     * take.  If this layer does not have an elevation dimension this will
     * return null
     */
    public abstract List<String> getElevationValues();
    public abstract String getElevationUnits();
    
    /**
     * @return a list of possible time values that this Layer can take,
     * in ISO 8601 format.
     * If this layer does not have a time dimension this will return null.
     */
    public abstract List<String> getTimeValues();
    
    /**
     * @return true if this Layer supports linear lat-lon projection
     * (which is the only projection that Google Earth can handle)
     */
    public boolean supportsPlateCarreeProjection()
    {
        return true;
    }
    
    /**
     * Gets the code for the Plate Carree projection, as used by
     * this.supportsPlateCarreeProjection()
     */
    protected abstract String getPlateCarreeProjectionCode();
    
    /**
     * @return the number of overlays that can be generated from this
     * Layer.  There will be one overlay for each combination of the
     * possible elevation value and time values.
     */
    public int getNumOverlays()
    {
        return this.numOverlays;
    }
    
    @Commit
    private void commit()
    {
        if (this.getElevationValues() != null && this.getElevationValues().size() > 0)
        {
            this.numOverlays *= this.getElevationValues().size();
        }
        if (this.getTimeValues() != null && this.getTimeValues().size() > 0)
        {
            this.numOverlays *= this.getTimeValues().size();
        }
        // Now set the supported projections for each child: supported
        // projections are inherited by child layers
        for (Layer child : this.getChildren())
        {
            // TODO set supported projections
            child.parent = this;
        }
    }

    public boolean isIncludeInKml()
    {
        return includeInKml;
    }

    public void setIncludeInKml(boolean includeInKml)
    {
        this.includeInKml = includeInKml;
    }

    public Layer getParent()
    {
        return parent;
    }
    
    protected static List<String> parseTimeValues(String commaSeparatedValues)
    {
        DateFormatter df = new DateFormatter();
        List<String> isoTimeValues = new ArrayList<String>();
        // TODO: deal with periodic values
        for (String isoDateTime : commaSeparatedValues.split(","))
        {
            // Google Earth gets confused if the ISO date/time
            // string is not full, hence we convert to a Date
            // and back again
            Date date = df.getISODate(isoDateTime);
            isoTimeValues.add(df.toDateTimeStringISO(date));
        }
        return isoTimeValues;
    }
}
